package com.yyj.util;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yyj.entity.AppSubwayData;
import com.yyj.vo.Tree;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author:汪彬彬
 * date:2025/2/17 9:30
 */
@Slf4j
public class MapUtils {

    private static final String DISTANCE = "http://restapi.amap.com/v3/distance?"; //距离

    private static final String DISTRICT = "https://restapi.amap.com/v3/config/district?";//行政区

    private static final String IP = "https://restapi.amap.com/v3/ip?";//ip定位

    private static final String GEO = "https://restapi.amap.com/v3/geocode/geo?";// 地理编码 API 服务地址

    private static final String REGEO = "https://restapi.amap.com/v3/geocode/regeo?";//逆地理编码 API 服务地址

    private static final String SUBWAY = "https://map.amap.com/service/subway?_";//逆地理编码 API 服务地址


   static String[] links = {
            "https://map.amap.com/service/subway?_1684218661470&srhdata=1100_drw_beijing.json",
            "https://map.amap.com/service/subway?_1684218693712&srhdata=3100_drw_shanghai.json",
            "https://map.amap.com/service/subway?_1684218708196&srhdata=4401_drw_guangzhou.json",
            "https://map.amap.com/service/subway?_1684218719262&srhdata=4403_drw_shenzhen.json",
            "https://map.amap.com/service/subway?_1684218731379&srhdata=4201_drw_wuhan.json",
            "https://map.amap.com/service/subway?_1684218743629&srhdata=1200_drw_tianjin.json",
            "https://map.amap.com/service/subway?_1684218759393&srhdata=3201_drw_nanjing.json",
            "https://map.amap.com/service/subway?_1684218773376&srhdata=8100_drw_xianggang.json",
            "https://map.amap.com/service/subway?_1684218803777&srhdata=5000_drw_chongqing.json",
            "https://map.amap.com/service/subway?_1684217707451&srhdata=3301_drw_hangzhou.json",
            "https://map.amap.com/service/subway?_1684218833591&srhdata=2101_drw_shenyang.json",
            "https://map.amap.com/service/subway?_1684218852774&srhdata=2102_drw_dalian.json",
            "https://map.amap.com/service/subway?_1684218869557&srhdata=5101_drw_chengdu.json",
            "https://map.amap.com/service/subway?_1684218886740&srhdata=2201_drw_changchun.json",
            "https://map.amap.com/service/subway?_1684218905074&srhdata=3205_drw_suzhou.json",
            "https://map.amap.com/service/subway?_1684218920973&srhdata=4406_drw_foshan.json",
            "https://map.amap.com/service/subway?_1684218936956&srhdata=5301_drw_kunming.json",
            "https://map.amap.com/service/subway?_1684218956105&srhdata=6101_drw_xian.json",
            "https://map.amap.com/service/subway?_1684218976721&srhdata=4101_drw_zhengzhou.json",
            "https://map.amap.com/service/subway?_1684219002370&srhdata=4301_drw_changsha.json",
            "https://map.amap.com/service/subway?_1684219044819&srhdata=3302_drw_ningbo.json",
            "https://map.amap.com/service/subway?_1684219064385&srhdata=3202_drw_wuxi.json",
            "https://map.amap.com/service/subway?_1684219087401&srhdata=3702_drw_qingdao.json",
            "https://map.amap.com/service/subway?_1684219109584&srhdata=3601_drw_nanchang.json",
            "https://map.amap.com/service/subway?_1684219127182&srhdata=3501_drw_fuzhou.json",
            "https://map.amap.com/service/subway?_1684219147299&srhdata=4419_drw_dongguan.json",
            "https://map.amap.com/service/subway?_1684219174915&srhdata=4501_drw_nanning.json",
            "https://map.amap.com/service/subway?_1684219192214&srhdata=3401_drw_hefei.json",
            "https://map.amap.com/service/subway?_1684219209797&srhdata=5201_drw_guiyang.json",
            "https://map.amap.com/service/subway?_1684219228846&srhdata=3502_drw_xiamen.json",
            "https://map.amap.com/service/subway?_1684219243963&srhdata=2301_drw_haerbin.json",
            "https://map.amap.com/service/subway?_1684219261162&srhdata=1301_drw_shijiazhuang.json",
            "https://map.amap.com/service/subway?_1684219275594&srhdata=6501_drw_wulumuqi.json",
            "https://map.amap.com/service/subway?_1684219292478&srhdata=3303_drw_wenzhou.json",
            "https://map.amap.com/service/subway?_1684219308833&srhdata=3701_drw_jinan.json",
            "https://map.amap.com/service/subway?_1684219330534&srhdata=6201_drw_lanzhou.json",
            "https://map.amap.com/service/subway?_1684219353633&srhdata=3204_drw_changzhou.json",
            "https://map.amap.com/service/subway?_1684219370051&srhdata=3203_drw_xuzhou.json",
            "https://map.amap.com/service/subway?_1684219391167&srhdata=1401_drw_taiyuan.json",
            "https://map.amap.com/service/subway?_1684219404866&srhdata=1501_drw_huhehaote.json",
            "https://map.amap.com/service/subway?_1684219420149&srhdata=4103_drw_luoyang.json"
    };

        public  static  String getUrl(String name){
            for(String str :links ){
                if(str.contains(name)){
                    return str;
                }
            }
           JSONObject jsonObject =geo(key,name);
           JSONObject object = (JSONObject) jsonObject.getJSONArray("geocodes").get(0);
           String code = object.getString("adcode").substring(0,4);
           return SUBWAY+System.currentTimeMillis()+"&srhdata="+code+"_drw_"+name+".json";
        }

    public static Tree subwayParser(String citys) {
    // 输出数组中的链接
        if(citys.contains("市")){
            citys=citys.substring(0,citys.indexOf("市"));
        }
        String cityPinYin = PinyinUtil.changeToTonePinYin(citys);
        String link = getUrl(cityPinYin);
        String subwayData =HttpClientUtil.doGet(link);
        try {
            JSONObject jsonObject = JSONObject.parseObject(subwayData);
            Tree tree = new Tree();
            // 获取城市名称
            String city = jsonObject.getString("s");
            tree.setId(jsonObject.getString("i"));
            tree.setCityName(jsonObject.getString("s"));
            List<Tree> treeList = new ArrayList<>();
            // 获取线路信息
            JSONArray lineArray = jsonObject.getJSONArray("l");
            for (int i = 0; i < lineArray.size(); i++) {
                JSONObject lineObject = lineArray.getJSONObject(i);
                if(!lineObject.getString("ls").equals("330100023132")) {//剔除脏数据 330100023132
                    Tree subTree = new Tree();
                    String la = lineObject.getString("la");
                    subTree.setCityName(city);
                    // 获取线路名称
                    subTree.setLineName(CheckIsNullOrEmptyUtil.isNullOrEmpty(la) ? lineObject.getString("ln") : lineObject.getString("ln") + "(" + la + ")");
                    subTree.setId(lineObject.getString("ls"));
                    List<Tree> subTreeList = new ArrayList<>();
                    JSONArray stationArray = lineObject.getJSONArray("st");
                    for (int j = 0; j < stationArray.size(); j++) {
                        JSONObject stationObject = stationArray.getJSONObject(j);
                        Tree thirdTree = new Tree();
                        thirdTree.setStation(stationObject.getString("n"));
                        thirdTree.setCityName(city);
                        thirdTree.setLineName(subTree.getLineName());
                        thirdTree.setId(stationObject.getString("sid"));
                        String coordinates = stationObject.getString("sl");
                        String[] latLng = coordinates.split(",");
                        String latitude = latLng[0];
                        String longitude = latLng[1];
                        thirdTree.setLongitude(longitude);
                        thirdTree.setLatitude(latitude);
                        subTreeList.add(thirdTree);
                    }
                    subTree.setList(subTreeList);
                    treeList.add(subTree);
                }
            }
            tree.setList(treeList);
            return  tree;
        } catch (Exception e) {
            throw new RuntimeException("暂未能获取改城市地铁信息");
        }

}
    public static JSONObject  geo(String key, String address){
        String url = GEO+"key="+key+"&address="+address;
        String results =HttpClientUtil.doGet(url);
        JSONObject jsonObject = JSONObject.parseObject(results);
        if(ObjectUtils.notEqual(jsonObject.get("infocode"),"10000")){
            throw new RuntimeException(jsonObject.getString("info"));
        }
        return  jsonObject;
    }


private  static final String key = "be7711d69f095d681b726094221806ed";



    public static Map<String,String>  regeo(String key, String location){
        String url = REGEO+"key="+key+"&location="+location;
        System.out.println(url);
        String results =HttpClientUtil.doGet(url);
        JSONObject jsonObject = JSONObject.parseObject(results);
        if(ObjectUtils.notEqual(jsonObject.get("infocode"),"10000")){
           throw new RuntimeException(jsonObject.getString("info"));
        }
        Map<String,String> map = new HashMap<>();
        String city = jsonObject.getJSONObject("regeocode").getJSONObject("addressComponent").getString("city");
        map.put("city",city);
        String cityCode = jsonObject.getJSONObject("regeocode").getJSONObject("addressComponent").getString("citycode");
        map.put("cityCode",cityCode);
        return  map;
    }


    public static String  getCityCode(String key, String location){
        String url = REGEO+"key="+key+"&location="+location;
        System.out.println(url);
        String results =HttpClientUtil.doGet(url);
        JSONObject jsonObject = JSONObject.parseObject(results);
        String result =jsonObject.getJSONObject("regeocode").getJSONObject("addressComponent").getString("citycode");
        return result.isEmpty()?null:result;
    }



    /**
     *  计算距离（km）
     * @param key   秘钥
     * @param startLon  起点经度
     * @param startLat  起点纬度
     * @param endLon   终点经度
     * @param endLat   终点纬度
     * @return
     */
    private static String getDistance(String key, String startLon, String startLat, String  endLon, String endLat){
        //返回起始地startAddr与目的地endAddr之间的距离，单位：米
        String origins=startLon+","+startLat;//起点坐标
        String destination=endLon+","+endLat;//终点坐标
        String url = DISTANCE+"key="+key+"&origins="+origins+"&destination="+destination;
        System.out.println(url);
        String results =HttpClientUtil.doGet(url);
        JSONObject jsonObject = JSONObject.parseObject(results);
        String json =jsonObject.getJSONArray("results").getJSONObject(0).toString();
        String distance = JSONObject.parseObject(json).getString("distance");
        //String distance = (String) JSONObject.parse(JSONObject.parse(results).getJSONArray("results").get(0).toString()).get("distance");
        return new BigDecimal(distance).divide(new BigDecimal(1000),1,RoundingMode.HALF_UP).toString();
    }



    private static String getDistrict(String key,String subdistrict, String keywords){
        String url = DISTRICT+"key="+key;
        if(subdistrict!=null){
            url=url+"&subdistrict="+subdistrict;
        }
        if(keywords!=null){
            url=url+"&keywords="+keywords;
        }
        System.out.println(url);
        String results =HttpClientUtil.doGet(url);
        return results;
    }

    private static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        }
        if(ip.equals("0:0:0:0:0:0:0:1")){
            return "127.0.0.1";
        }
        return ip;
    }

    public static String getCity(String key, HttpServletRequest request){
        String url = IP+"key="+key+"&ip="+getIpAddress(request);
        System.out.println(url);
        String results =HttpClientUtil.doGet(url);
        JSONObject jsonObject = JSONObject.parseObject(results);
        String rectangle = jsonObject.getString("rectangle");
        if(rectangle==null||rectangle.isEmpty()){
            return null;
        }
        String location = rectangle.substring(0,rectangle.indexOf(";"));
        Map<String,String> map = regeo(key,location);
        return map.get("cityCode");
    }





    private static double rad(String d) {
        return Double.valueOf(d) * Math.PI / 180.0;
    }
        public static BigDecimal getDistance2(String longitude1, String latitude1, String longitude2, String latitude2) {
        double radLat1 = rad(latitude1);
        double radLat2 = rad(latitude2);
        double a = radLat1 - radLat2;
        double b = rad(longitude1) - rad(longitude2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_AVG_RADIUS;
        s = Math.round(s * 10000d) / 10000d;
        return new BigDecimal(s).divide(new BigDecimal(1000),1,RoundingMode.HALF_UP);
    }


    /**
     * 地球平均半径（单位：米）
     */
    private static final double EARTH_AVG_RADIUS = 6371000;

    /**
     * 方法二：（反余弦计算方式）
     *
     * @param longitude1 第一点的经度
     * @param latitude1  第一点的纬度
     * @param longitude2 第二点的经度
     * @param latitude2  第二点的纬度
     * @return 返回的距离，单位m
     */
    public static double getDistance3(double longitude1, double latitude1, double longitude2, double latitude2) {
        // 经纬度（角度）转弧度。弧度作为作参数，用以调用Math.cos和Math.sin
        // A经弧度
        double radiansAX = Math.toRadians(longitude1);
        // A纬弧度
        double radiansAY = Math.toRadians(latitude1);
        // B经弧度
        double radiansBX = Math.toRadians(longitude2);
        // B纬弧度
        double radiansBY = Math.toRadians(latitude2);

        // 公式中“cosβ1cosβ2cos（α1-α2）+sinβ1sinβ2”的部分，得到∠AOB的cos值
        double cos = Math.cos(radiansAY) * Math.cos(radiansBY) * Math.cos(radiansAX - radiansBX) + Math.sin(radiansAY) * Math.sin(radiansBY);
        // System.out.println("cos = " + cos); // 值域[-1,1]

        // 反余弦值
        double acos = Math.acos(cos);
        // System.out.println("acos = " + acos); // 值域[0,π]
        // System.out.println("∠AOB = " + Math.toDegrees(acos)); // 球心角 值域[0,180]

        // 最终结果
        return EARTH_AVG_RADIUS * acos;
    }



}
